package com.maodou.android.utils

import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec

/**
 * @Author Xing
 * @CreateTime 2025年09月23日
 * @Description TODO
 */
object EncryptUtils {

    fun generateTotp(secret: ByteArray, timeMillis: Long, periodSeconds: Int, digits: Int): String {
        val timeStep = (timeMillis / 1000L) / periodSeconds
        val data = ByteArray(8)
        var value = timeStep
        for (i in 7 downTo 0) {
            data[i] = (value and 0xFF).toByte()
            value = value ushr 8
        }
        val mac = Mac.getInstance("HmacSHA1")
        mac.init(SecretKeySpec(secret, "HmacSHA1"))
        val hash = mac.doFinal(data)
        val offset = hash.last().toInt() and 0x0F
        val binary = ((hash[offset].toInt() and 0x7f) shl 24) or
                ((hash[offset + 1].toInt() and 0xff) shl 16) or
                ((hash[offset + 2].toInt() and 0xff) shl 8) or
                (hash[offset + 3].toInt() and 0xff)
        val otp = binary % pow10(digits)
        return otp.toString().padStart(digits, '0')
    }

    fun pow10(n: Int): Int = when (n) {
        0 -> 1
        1 -> 10
        2 -> 100
        3 -> 1_000
        4 -> 10_000
        5 -> 100_000
        6 -> 1_000_000
        7 -> 10_000_000
        8 -> 100_000_000
        else -> 1_000_000_000
    }

    // 轻量 Base32 解码（RFC 4648，不支持分隔符）
    fun base32Decode(input: String): ByteArray {
        val alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
        val cleaned = input.trim().replace("=", "").replace(" ", "").uppercase()
        val output = ArrayList<Byte>(cleaned.length * 5 / 8)
        var buffer = 0
        var bitsLeft = 0
        for (ch in cleaned) {
            val idx = alphabet.indexOf(ch)
            if (idx == -1) throw IllegalArgumentException("Invalid Base32 char: $ch")
            buffer = (buffer shl 5) or idx
            bitsLeft += 5
            if (bitsLeft >= 8) {
                bitsLeft -= 8
                output.add(((buffer shr bitsLeft) and 0xFF).toByte())
            }
        }
        return output.toByteArray()
    }

}